﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.FtpClient;
using System.IO;
using Ionic.Zip;
using System.Xml.Serialization;

namespace ZipUp
{
    class Program
    {
        static void Main(string[] args)
        {
            switch (args.Length)
            {
                case 0:
                    {
                        FtpSettings.GetTemplate().Serialize(System.Console.Out);
                        Console.WriteLine();
                        JobList jobList = new JobList();

                        Job jobA = new Job()
                        {
                            Destination = "backup-logs.zip"
                        };
                        jobA.Sources.Add(new Source() { IncludeEmptyFolders = true, IncludeSubdirs = true, Mask = "*.log", Path = "/logs" });

                        Job jobB = new Job()
                        {
                            Destination = "backup-data.zip"
                        };
                        jobB.Sources.Add(new Source() { IncludeEmptyFolders = true, IncludeSubdirs = false, Mask = "*.db", Path = "/database" });


                        (jobA).Serialize(System.Console.Out);

                        Console.WriteLine();

                        jobList.Add(jobA);
                        jobList.Add(jobB);

                        jobList.Serialize(Console.Out);

                        Console.ReadKey();
                    }
                    break;
                case 2:
                    {
                        FtpSettings ftpSettings = EasySerializationHelper.FromXmlFile<FtpSettings>(args[0]);
                        JobList jobList = EasySerializationHelper.FromXmlFile<JobList>(args[1]);
                        //List<Job> jobList = (List<Job>)(new XmlSerializer(typeof(List<Job>), new XmlRootAttribute("Jobs"))).Deserialize(new FileStream(args[1], FileMode.Open));
                        //List<Job> jobList = EasySerializationHelper.FromXmlFile<List<Job>>(args[1]);

                        ZipUp(ftpSettings, jobList);
                    }
                    break;
                default:
                    System.Console.WriteLine("Invalid number of config files: correct number is 2, settings for ftp, followed by settings for job");
                    break;
            }
        }

        static void ZipUp(FtpSettings ftpSettings, IList<Job> jobList)
        {
            FtpClient ftpc = new FtpClient();
            ftpc.Host = ftpSettings.HostSettings.HostName;
            ftpc.Credentials = new NetworkCredential(ftpSettings.UserSettings.UserName, ftpSettings.UserSettings.Password);

            int kJob = 1, nJobs = jobList.Count;
            foreach (Job job in jobList)
            {
                Stream upStream = ftpc.OpenWrite(job.Destination, FtpDataType.Binary);
                ZipOutputStream zStream = new ZipOutputStream(upStream);

                int kSource = 1, nSources = job.Sources.Count;
                foreach (Source source in job.Sources)
                {
                    if (source.IncludeEmptyFolders)
                        foreach (string dName in Directory.EnumerateDirectories(source.Path, source.Mask, source.IncludeSubdirs ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
                        {
                            zStream.PutNextEntry(dName.Replace(source.Path, string.Empty) + "/"); // the trailing "/" makes the entry a folder in the archive
                        }

                    IEnumerable<string> sourceFiles = Directory.EnumerateFiles(source.Path, source.Mask, source.IncludeSubdirs ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
                    {
                        int k = 0, n = sourceFiles.Count();
                        foreach (string fName in sourceFiles)
                        {
                            if ((System.Console.KeyAvailable) && (System.Console.ReadKey(true).Key == ConsoleKey.Escape))
                                break;
                            string relFName = fName.Replace(source.Path, string.Empty);
                            Console.WriteLine("[Job {5}/{6} - Source {3}/{4} - File {1}/{2}]@{7}: {0}", relFName, ++k, n, kSource, nSources, kJob, nJobs, DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss-FF"));
                            zStream.PutNextEntry(relFName);
                            Stream iStream = File.OpenRead(fName);
                            iStream.CopyTo(zStream);
                            iStream.Close();
                        }
                    }
                    kSource++;
                }
                kJob++;

                zStream.Close();
                upStream.Close();
            }

            ftpc.Disconnect();
        }
    }
}
